package com.maint.m.utils

import android.content.Context
import android.content.SharedPreferences
import android.util.Log
import com.arthenica.ffmpegkit.FFmpegKit
import com.arthenica.ffmpegkit.FFmpegSession
import kotlinx.coroutines.*
import java.io.File
import java.io.FileOutputStream
import java.util.concurrent.ConcurrentLinkedQueue

class H264RtpStreamer(private val context: Context) {
    private val TAG = "H264RtpStreamer::"
    private val PREFS_NAME = "streaming_prefs"
    private val KEY_RTMP_URL = "rtmp_url"

    private var session: FFmpegSession? = null
    private var pipeFile: File? = null
    private var writeJob: Job? = null

    private val frameQueue = ConcurrentLinkedQueue<ByteArray>()
    private val ioScope = CoroutineScope(Dispatchers.IO + SupervisorJob())
    private var pushStartTime: Long = 0
    private var totalFramesSent: Long = 0

    /**
     * 启动推流
     */
    fun startPush() {
        Log.d(TAG, "开始启动推流...")
        pushStartTime = System.currentTimeMillis()
        totalFramesSent = 0
        
        // 重置状态
        session = null
        writeJob = null
        frameQueue.clear()
        
        Log.d(TAG, "创建命名管道...")
        pipeFile = createPipeFile()
        
        Log.d(TAG, "获取RTMP URL配置...")
        val outputUrl = getRtmpUrlFromConfig()
        Log.d(TAG, "使用推流地址: $outputUrl")

        Log.d(TAG, "构建FFmpeg命令参数...")
        val cmd = listOf(
            "-loglevel", "error",
            "-err_detect", "ignore_err", // 忽略解码错误
            "-i", pipeFile!!.absolutePath,
            "-c", "copy",
            "-f", "flv",
            outputUrl
        )

        Log.i(TAG, "执行FFmpeg推流命令: ${cmd.joinToString(" ")}")
        session = FFmpegKit.executeAsync(cmd.joinToString(" ")) { s ->
            val duration = System.currentTimeMillis() - pushStartTime
            Log.i(TAG, "FFmpeg推流结束: 状态=${s.state}, 持续时间=${duration}ms, 发送帧数=${totalFramesSent}")
            Log.d(TAG, "FFmpeg退出码: ${s.returnCode}, 失败原因: ${s.failStackTrace}")
        }

        Log.d(TAG, "启动帧写入循环...")
        startWriterLoop()

        // 写入首帧 SPS/PPS，防止 FFmpeg 立即退出
        ioScope.launch {
            delay(200) // 等待 FFmpeg 启动
            Log.d(TAG, "写入初始SPS/PPS配置帧...")
            writeDummySpsPps()
        }

        Log.i(TAG, "RTMP推流已启动，等待连接服务器...")
    }

    /**
     * 异步写入帧循环
     */
    private fun startWriterLoop() {
        val pipe = pipeFile ?: return
        Log.d(TAG, "初始化帧写入循环到管道: ${pipe.absolutePath}")
        
        writeJob = ioScope.launch {
            try {
                Log.d(TAG, "打开管道输出流...")
                FileOutputStream(pipe, true).use { fos ->
                    Log.d(TAG, "管道输出流已打开，开始帧写入循环")
                    while (isActive) {
                        val frame = frameQueue.poll()
                        if (frame != null && frame.isNotEmpty()) {
                            fos.write(frame)
                            fos.flush()
                            totalFramesSent++
                            
                            // 每10帧打印一次状态，避免日志过多
                            if (totalFramesSent % 10L == 0L) {
                                Log.d(TAG, "已发送帧数: $totalFramesSent, 当前队列大小: ${frameQueue.size}")
                            }
                        } else {
                            delay(5)
                        }
                    }
                }
            } catch (e: Exception) {
                Log.e(TAG, "帧写入循环异常", e)
            } finally {
                Log.d(TAG, "帧写入循环已停止")
            }
        }
    }

    /**
     * 写入来自 onVideoH264Stream 的实时帧
     */
    fun writeFrame(data: ByteArray) {
        if (data.isEmpty()) {
            Log.w(TAG, "尝试写入空帧，已忽略")
            return
        }
        
        // 记录帧信息（每50帧打印一次详细信息，避免日志过多）
        if (totalFramesSent % 50L == 0L) {
            Log.d(TAG, "收到新帧，大小: ${data.size}字节, 当前队列大小: ${frameQueue.size}")
        }
        
        // 防止队列积压
        if (frameQueue.size > 60) {
            frameQueue.poll()
            Log.w(TAG, "队列已满，丢弃最早的帧，当前队列大小: ${frameQueue.size}")
        }
        
        frameQueue.offer(data)
        if (frameQueue.size > 30) {
            Log.w(TAG, "警告: 队列积压，当前大小: ${frameQueue.size}")
        }
    }

    /**
     * 从配置中获取RTMP URL
     */
    private fun getRtmpUrlFromConfig(): String {
        try {
            Log.d(TAG, "尝试从SharedPreferences读取RTMP URL配置...")
            // 从SharedPreferences读取
            val prefs = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
            val savedUrl = prefs.getString(KEY_RTMP_URL, null)
            if (savedUrl != null && savedUrl.isNotEmpty()) {
                Log.i(TAG, "成功从配置中读取RTMP URL: $savedUrl")
                return savedUrl
            }
            Log.d(TAG, "配置中未找到RTMP URL或为空")
        } catch (e: Exception) {
            Log.e(TAG, "读取配置失败: ${e.message}", e)
        }

        // 返回默认的线上流媒体服务器地址
        val defaultUrl = BuildConfig.DEFAULT_RTMP_URL
        Log.i(TAG, "使用默认RTMP URL: $defaultUrl")
        return defaultUrl
    }

    /**
     * 停止推流
     */
    fun stopPush() {
        Log.i(TAG, "开始停止推流...")
        
        // 取消帧写入任务
        writeJob?.let {
            Log.d(TAG, "取消帧写入任务...")
            it.cancel()
            writeJob = null
        }
        
        // 取消FFmpeg会话
        session?.let {
            Log.d(TAG, "取消FFmpeg会话...")
            FFmpegKit.cancel(it.sessionId)
            session = null
        }
        
        // 删除管道文件
        pipeFile?.let {
            Log.d(TAG, "删除管道文件...")
            if (it.delete()) {
                Log.d(TAG, "管道文件已删除: ${it.absolutePath}")
            } else {
                Log.w(TAG, "删除管道文件失败: ${it.absolutePath}")
            }
            pipeFile = null
        }
        
        // 清空帧队列
        val queueSize = frameQueue.size
        frameQueue.clear()
        
        val duration = System.currentTimeMillis() - pushStartTime
        Log.i(TAG, "推流已完全停止 - 持续时间: ${duration}ms, 总发送帧数: $totalFramesSent, 清空队列帧数: $queueSize")
    }

    /**
     * 创建命名管道
     */
    private fun createPipeFile(): File {
        Log.d(TAG, "开始创建命名管道...")
        val pipe = File(context.filesDir, "livepipe.h264")
        
        // 如果管道已存在，先删除
        if (pipe.exists()) {
            Log.d(TAG, "管道文件已存在，删除中...")
            if (pipe.delete()) {
                Log.d(TAG, "旧管道文件已删除")
            } else {
                Log.w(TAG, "删除旧管道文件失败")
            }
        }
        
        try {
            Log.d(TAG, "执行mkfifo命令创建新管道...")
            val process = Runtime.getRuntime().exec("mkfifo ${pipe.absolutePath}")
            val exitCode = process.waitFor()
            
            if (exitCode == 0) {
                Log.i(TAG, "管道创建成功，路径: ${pipe.absolutePath}")
            } else {
                Log.e(TAG, "管道创建失败，exitCode: $exitCode")
                // 创建一个普通文件作为备选
                pipe.createNewFile()
                Log.w(TAG, "已创建普通文件作为备选: ${pipe.absolutePath}")
            }
        } catch (e: Exception) {
            Log.e(TAG, "创建管道时发生异常", e)
            try {
                // 创建一个普通文件作为备选
                pipe.createNewFile()
                Log.w(TAG, "已创建普通文件作为备选: ${pipe.absolutePath}")
            } catch (innerE: Exception) {
                Log.e(TAG, "创建备选文件也失败", innerE)
            }
        }
        
        return pipe
    }

    /**
     * 写入 SPS/PPS 首帧
     */
    private fun writeDummySpsPps() {
        try {
            Log.d(TAG, "准备写入SPS/PPS配置帧...")
            FileOutputStream(pipeFile!!, true).use { fos ->
                // 使用更标准的SPS/PPS数据，避免VUI解析问题
                val spsPps = byteArrayOf(
                    0x00, 0x00, 0x00, 0x01, 0x67, 0x42, 0x00, 0x1F,
                    0xA6.toByte(), 0x80.toByte(), 0x78, 0x02, 0x27, 0xE5.toByte(), 0x80.toByte(), 0x00,
                    0x00, 0x03, 0x00, 0x40, 0x00, 0x00, 0x07, 0x82.toByte(),
                    0xEE.toByte(), 0x3C, 0x11, 0x00, 0x00, 0x00, 0x01, 0x68,
                    0xCE.toByte(), 0x38, 0x80.toByte()
                )
                
                fos.write(spsPps)
                fos.flush()
                Log.i(TAG, "SPS/PPS配置帧写入成功，大小: ${spsPps.size}字节")
                totalFramesSent++
            }
        } catch (e: Exception) {
            Log.e(TAG, "写入SPS/PPS配置帧失败", e)
        }
    }
    
    /**
     * 获取当前推流状态信息
     */
    fun getStreamStats(): Map<String, Any> {
        val duration = if (pushStartTime > 0) (System.currentTimeMillis() - pushStartTime) else 0
        return mapOf(
            "isStreaming" to (session != null),
            "durationMs" to duration,
            "totalFrames" to totalFramesSent,
            "queueSize" to frameQueue.size,
            "url" to (getRtmpUrlFromConfig())
        )
    }
    
    /**
     * 检查推流是否正在进行
     */
    fun isStreaming(): Boolean {
        val isActive = session != null && writeJob?.isActive == true
        Log.d(TAG, "检查推流状态: isStreaming=$isActive")
        return isActive
    }
}
